package test.serverframe.armc.server.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import org.codehaus.jackson.map.ObjectMapper;
import org.yaml.snakeyaml.Yaml;

import java.io.*;
import java.nio.charset.Charset;
import java.util.*;

/**
 * @Auther: lc
 * @Date: 2018/10/9 16:22
 * @Description: 配置管理中心-json工具类
 */
public class JsonUtil {

    /**
     * @param map 待转换的map
     * @desc: 将map转换为json
     * @return:
     * @auther: lc
     * @date: 2018/10/15 14:53
     */
    public static String mapToJson(Map map) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        String mapJson = objectMapper.writeValueAsString(map);
        return mapJson;
    }

    /**
     * @param str 文件路径
     * @desc: properties文件转为json字符串
     * @return:
     * @auther: lc
     * @date: 2018/10/15 14:54
     */
    public static String propertiesToJson(String str) throws IOException {
        //注释转义
        String tranStr = transferencePropertestStr(str);
        //字符串转为字节输入流
        InputStream inputStream = strToStream(tranStr);
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        String pair = "";
        //构造map
        Map<String, String> map = new LinkedHashMap<String, String>();
        while ((pair = br.readLine()) != null) {
            //读取key value
            String[] strings = pair.split("=");
            if (strings.length == 2) {
                map.put(strings[0], strings[1]);
            }
        }
        inputStream.close();
        br.close();
        String jsonStr = mapToJson(map);
        return jsonStr;
    }

    /**
     * jsonToYamlFile(含注释转义)
     *
     * @param filePath   文件路径（不含文件名）
     * @param jsonString json字符串
     * @param fileName   文件名
     * @return:
     * @auther: lc
     * @date: 2018/9/12 15:50
     */
    public static void jsonToYamlFile(String jsonString, String filePath, String fileName) throws JsonProcessingException, IOException {
        // 解析JSON 注释反转义
        jsonString = jsonString.replace("numsign", "#").replace("colon", ":");
        JsonNode jsonNodeTree = new com.fasterxml.jackson.databind.ObjectMapper().readTree(jsonString);
        // 存储为 YAML
        String jsonAsYaml = new YAMLMapper().writeValueAsString(jsonNodeTree);
        //截取前四个字符（ ---）
        jsonAsYaml = jsonAsYaml.substring(4).replace("\"", "");
        //写入到目标文件
        File dir = new File(filePath);
        if (!dir.exists()) {
            dir.mkdir();
        }
        FileWriter writer = new FileWriter(filePath + "\\" + fileName);
        //注释反转义
        jsonAsYaml = jsonAsYaml.replace("note: ", "").replaceAll("note\\d+: ", "");
        writer.write(jsonAsYaml);
        writer.close();
    }

    /**
     * jsonToPropertiesFile(含注释转义)
     *
     * @param filePath   文件路径（不含文件名）
     * @param jsonString json字符串
     * @param fileName   文件名
     * @return:
     * @auther: lc
     * @date: 2018/9/27 10:02
     */
    public static void jsonToPropertiesFile(String jsonString, String filePath, String fileName) throws JsonProcessingException, IOException {
        // 解析JSON 注释反转义
        jsonString = jsonString.replace("numsign", "#").replace("colon", "=");
        //将json转换为map
        Map<String, Map<String, String>> map = JSON.parseObject(
                jsonString.trim(), LinkedHashMap.class, Feature.OrderedField);
        //写入目标文件
        File dir = new File(filePath);
        if (!dir.exists()) {
            dir.mkdir();
        }
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath + "\\" + fileName));
        //遍历map 注释反转义
        for (String key : map.keySet()) {
            String record = key + "=" + map.get(key);
            record = record.replaceAll("note\\d+=", "").replace("note=", "");
            System.out.println(record);
            bufferedWriter.write(record);
            bufferedWriter.newLine();
            bufferedWriter.flush();
        }
        bufferedWriter.close();
    }

    /**
     * yaml转json 带注释转义
     *
     * @param str yaml文件路径
     * @return:
     * @auther: lc
     * @date: 2018/9/12 15:24
     */
    public static String yamlToJsonContainNote(String str) throws IOException {
        //注释转义
        String tranStr = transferenceYamlStr(str);
        //字符串转换为字节输入流
        InputStream inputStream = strToStream(tranStr);
        //字节输入流转换为json字符串
        String json = yamlToJson(inputStream);
        return json;
    }

    /**
     * @param str 待转义字符
     * @desc: yaml注释转义
     * @return:
     * @auther: lc
     * @date: 2018/10/15 15:08
     */
    public static String transferenceYamlStr(String str) throws IOException {
        StringBuffer sb = new StringBuffer(str);
        //转义单独为行的注释
        int temp = 0;
        for (int i = 0; i < sb.length() - 1; i++) {
            //如果当前字符为换行则截取之后的字符串
            if (sb.charAt(i) == '\n') {
                String s = sb.substring(i);
                //对于截取的字符串做循环判断，只循环一行
                for (int j = 0; j < s.length() - 1; j++) {
                    //如果为‘#’开头，则为注释开始，做转移，并且退出循环
                    if (s.charAt(j) == '#') {
                        //为了让key不重复，用temp计数器
                        sb.replace(i + j, i + j + 1, "note" + temp++ + ": #");
                        String s2 = sb.substring(i + j + 8);
                        break;
                    }
                    //如果为换行或者‘ ’则退出本次循环
                    else if (s.charAt(j) == '\n' || s.charAt(j) == ' ') {
                        continue;
                    }
                    //如果未为其他字符则退出循环
                    else {
                        break;
                    }
                }
            }
        }
        String s = sb.toString();
        //转义所有的#
        s = s.replaceAll("#", "numsign");
        //转义注释在配置信息后中出现的‘：’，以及首行注释
        BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(s.getBytes(Charset.forName("utf8"))), Charset.forName("utf8")));
        String line;
        StringBuffer strbuf = new StringBuffer();
        temp = 0;
        while ((line = br.readLine()) != null) {
            if (!"".equals(line.trim())) {
                //转义首行注释
                if (temp == 0) {
                    line = line.replace("numsign", "note: numsign");
                }
                if (line.contains("numsign")) {
                    String[] pves = line.split("numsig");
                    String pes = pves[1];
                    String pop = pes.replace(":", "colon");
                    line = pves[0] + "numsign" + pop;
                }
                temp++;
                strbuf.append(line + "\r\n");
            }
        }
        return strbuf.toString();
    }

    /**
     * @param str 待转义字符
     * @desc: properties转义注释
     * @return:
     * @auther: lc
     * @date: 2018/10/15 15:09
     */
    public static String transferencePropertestStr(String str) throws IOException {
        StringBuffer sb = new StringBuffer(str);
        //转义单独为行的注释
        int temp = 0;
        for (int i = 0; i < sb.length() - 1; i++) {
            //如果当前字符为换行则截取之后的字符串
            if (sb.charAt(i) == '\n') {
                String s = sb.substring(i);
                //对于截取的字符串做循环判断，只循环一行
                for (int j = 0; j < s.length() - 1; j++) {
                    //如果为‘#’开头，则为注释开始，做转移，并且退出循环
                    if (s.charAt(j) == '#') {
                        //为了让key不重复，用temp计数器
                        sb.replace(i + j, i + j + 1, "note" + temp++ + "=#");
                        String s2 = sb.substring(i + j + 8);
                        break;
                    }
                    //如果为换行或者‘ ’则退出本次循环
                    else if (s.charAt(j) == '\n' || s.charAt(j) == ' ') {
                        continue;
                    }
                    //如果未为其他字符则退出循环
                    else {
                        break;
                    }
                }
            }
        }
        String s = sb.toString();
        //转义所有的#
        s = s.replaceAll("#", "numsign");
        //转义注释在配置信息后中出现的‘=’，以及首行注释
        BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(s.getBytes(Charset.forName("utf8"))), Charset.forName("utf8")));
        String line;
        StringBuffer strbuf = new StringBuffer();
        temp = 0;
        while ((line = br.readLine()) != null) {
            if (!"".equals(line.trim())) {
                //转义首行注释
                if (temp == 0) {
                    line = line.replace("numsign", "note=numsign");
                }
                if (line.contains("numsign")) {
                    String[] pves = line.split("numsig");
                    String pes = pves[1];
                    String pop = pes.replace("=", "colon");
                    line = pves[0] + "numsig" + pop;
                }
                temp++;
                strbuf.append(line + "\r\n");
            }
        }
        return strbuf.toString();
    }

    /**
     * @param str 待转换字符串
     * @desc: str 转换为inputStream
     * @return:
     * @auther: lc
     * @date: 2018/10/15 15:09
     */
    public static InputStream strToStream(String str) {
        InputStream is = new ByteArrayInputStream(str.getBytes());
        return is;
    }

    /**
     * @param is 带转换输入流
     * @desc: yaml输入流转为json字符串
     * @return:
     * @auther: lc
     * @date: 2018/10/15 15:10
     */
    public static String yamlToJson(InputStream is) throws IOException {
        Yaml yaml = new Yaml();//实例化解析器
        Map map = yaml.loadAs(is, LinkedHashMap.class);//装载的对象，这里使用LinkedHahMap（可以控制遍历顺序） 当然也可使用自己写的对象
        // Map breakMap = getBreakMap(map);
        String yamlJson = mapToJson(map);
        return yamlJson;
    }

    /**
     * @Descripttion 获取jsonArray （data不为list）
     * @Author LSY
     * @Date 16:45
     * @Param [ob]
     * @Return
     **/
    public static JSONArray getJSONArrayCtList(Object ob) {
        String jsonStr = JSONObject.toJSONString(ob);
        JSONObject jsonObject = (JSONObject) JSON.parse(jsonStr);
        JSONObject data = jsonObject.getJSONObject("data");
        JSONArray jsonArray = (JSONArray) data.get("list");
        return jsonArray;
    }

    /**
     * @Descripttion 获取jsonArray （data为list）
     * @Author LSY
     * @Date 16:45
     * @Param [ob]
     * @ReturngetJSONArray
     **/
    public static JSONArray getJSONArray(Object ob) {
        String jsonStr = JSONObject.toJSONString(ob);
        JSONObject jsonObject = (JSONObject) JSON.parse(jsonStr);
        JSONArray jsonArray = (JSONArray) jsonObject.get("data");
        return jsonArray;
    }

    /**
     * 给定出参和入参模型 返回入参的真实数据
     *
     * @param inStr  入参模型
     * @param outStr 出参
     * @return 入参真实数据
     */
    public static String convert(String outStr, String inStr, String prefix) {
        Map map1 = (Map) JSON.parse(outStr);
        Map hashMap = new HashMap();
        hashMap.put(prefix, map1);
        Map newMap = getNewMap(hashMap);
        Map map2 = (Map) JSON.parse(inStr);
        reValue(newMap, map2);
        String outJSON = JSON.toJSONString(map2);
        return outJSON;
    }


    /**
     * 递归方法:
     * 当map2中的value为map1的key时,将map2中的value替换为map1中对应的value
     *
     * @param map1
     * @param map2
     * @return
     */
    public static Map reValue(Map map1, Map map2) {
        for (Object key1 : map1.keySet()) {
            for (Object key2 : map2.keySet()) {
                if (map2.get(key2) instanceof Map) {
                    reValue(map1, (Map) map2.get(key2));
                } else {
                    if (key1.equals(map2.get(key2))) {
                        map2.put(key2, map1.get(key1));
                    }
                }

            }

        }
        return map2;
    }


    /**
     * 将多级Map转换成key为AA.BB.CC的形式
     *
     * @param key
     * @param map
     * @param newMap
     */
    public static void keyConvert(StringBuilder key, Map<String, Object> map, Map<String, Object> newMap) {
        Set<Map.Entry<String, Object>> entries = map.entrySet();
        for (Map.Entry entry : entries) {
            key.append(entry.getKey());
            Object value = entry.getValue();
            if (value instanceof Map) {
                key.append(".");
                keyConvert(key, (Map<String, Object>) value, newMap);
                key = new StringBuilder("");

            } else {
                newMap.put(key.toString(), value);
                if (!key.toString().contains(".")) {
                    key = new StringBuilder("");
                } else {
                    String substring = key.substring(0, key.lastIndexOf(".") + 1);
                    key = new StringBuilder(substring);
                }
            }
        }

    }

    public static Map getNewMap(Map<String, Object> map1) {
        Map newMap = new LinkedHashMap();
        keyConvert(new StringBuilder(""), map1, newMap);
        return newMap;
    }

    /**
     * 任务图和接口图的数组字符串
     *
     * @param list
     * @return
     */
    public static String parseString(List<String> list) {
        List<String> ids = new ArrayList<>();
        for (String str : list) {
            ids.add("\"" + str + "\"");
        }
        return ids.toString();
    }

    public static void main(String[] args) {

        //String outValue="{\"name\":\"BeJson\",\"url\":\"http://www.bejson.com\",\"page\":88,\"isNonProfit\":true,\"address\":{\"street\":\"科技园路.\",\"city\":\"江苏苏州\",\"country\":\"中国\"},\"links\":[{\"name\":\"Google\",\"url\":\"http://www.google.com\"},{\"name\":\"Baidu\",\"url\":\"http://www.baidu.com\"},{\"name\":\"SoSo\",\"url\":\"http://www.SoSo.com\"}]}";
        //String inValue="{\"name\":\"name\",\"url\":\"url\",\"page\":\"port\",\"isNonProfit\":\"isNonProfit\",\"address\":{\"street\":\"address.street\",\"city\":\"address.city\",\"country\":\"address.country\"}}";
        String a = "{\"msg\":\"success\",\"data\":{\"expire\":43200,\"token\":\"2db584f1009df413b5942a766dc41c30\"},\"status\":0}";
        String b = "{\"token\":\"aa.data.token\"}";

        
        String c = "{\"status\":0,\"msg\":\"success\",\"data\":{\"expire\":43200,\"token\":\"a5fc0d153e40b7523dd048be076e8c15\"}}";
        String outJSON = JsonUtil.convert(c, b, "aa");
        System.out.println(outJSON);
        //List<String> list = new ArrayList<>();
        //List<String> list2 = new ArrayList<>();
        //list.add("ffff");
        //list.add("ffff");
        //for (String str : list) {
        //    String s = "\"" + str + "\"";
        //    list2.add(s);
        //}
        //System.out.println(list2.toString());

    }

}
